<template>
    <el-dialog title="角色权限" :close-on-click-modal="false" :close-on-press-escape="false" :show-close="true"
        :visible.sync="visible" @close="visible = false">
        <div v-loading="loading">
            <el-tree ref="treeRef" :data="data" show-checkbox node-key="id" :default-expanded-keys="defaultOpenIds"
                :props="defaultProps" :default-expand-all="true" :check-strictly="true">
            </el-tree>
        </div>
        <div slot="footer" class="dialog-footer">
            <el-button @click="visible = false">取 消</el-button>
            <el-button type="primary" @click="sub" :loading="loading">确 定</el-button>
        </div>
    </el-dialog>
</template>

<script>
import { permissionTree } from '../api/product';
import { roleAssignPermissions, roleGetPermissions } from '../api/role';

export default {
    data() {
        return {
            roleId: null,
            data: [],
            defaultOpenIds: [],
            visible: false,
            loading: false,
            defaultProps: {
                children: 'children',
                label: 'permissionName'
            }
        }
    },
    created() { },
    methods: {
        /**
         * 获取需要展开的节点ID集合
         * @param {Array} treeData 树形数据
         * @param {Array} checkedKeys 当前选中的节点ID集合
         * @return {Array} 需要展开的节点ID数组
         */
        getExpandedKeys(treeData, checkedKeys) {
            const expandedKeys = new Set();
            const checkedSet = new Set(checkedKeys);

            // 递归遍历树节点
            function traverse(nodes) {
                nodes.forEach(node => {
                    // 如果当前节点有子节点
                    if (node.children && node.children.length > 0) {
                        // 检查子节点是否有被选中的
                        const hasCheckedChild = node.children.some(child =>
                            checkedSet.has(child.id) || traverse([child])
                        );

                        // 如果有子节点被选中，则当前节点需要展开
                        if (hasCheckedChild) {
                            expandedKeys.add(node.id);
                        }

                        return hasCheckedChild;
                    }
                    // 叶子节点直接返回是否选中
                    return checkedSet.has(node.id);
                });
            }

            traverse(treeData);
            return Array.from(expandedKeys);
        },
        // 处理树节点回显数据
        processTreeDataForDisplay(treeData, checkedKeys) {

            const checkedSet = new Set(checkedKeys);
            const displayKeys = new Set(); // 用于显示的节点ID

            // 递归处理节点
            function processNode(node) {
                if (!node.children || node.children.length === 0) {
                    // 叶子节点，如果在选中列表中则显示
                    if (checkedSet.has(node.id)) {
                        displayKeys.add(node.id);
                    }
                    return checkedSet.has(node.id);
                }

                // 处理子节点
                let allChildrenChecked = true;
                let someChildrenChecked = false;

                for (const child of node.children) {
                    const childChecked = processNode(child);
                    allChildrenChecked = allChildrenChecked && childChecked;
                    someChildrenChecked = someChildrenChecked || childChecked;
                }

                // 如果所有子节点都选中，且父节点也在选中列表中，则显示父节点
                if (allChildrenChecked && checkedSet.has(node.id)) {
                    displayKeys.add(node.id);
                }

                return someChildrenChecked;
            }

            // 遍历所有节点
            for (const node of treeData) {
                processNode(node);
            }

            const result = Array.from(displayKeys);
            return result;
        },
        // 确保树节点状态正确
        ensureCorrectTreeState() {
            const treeRef = this.$refs.treeRef;
            if (!treeRef) return;
            // 验证树状态是否正确
            this.validateTreeState();
        },
        // 简单的回显方法
        simpleTreeDisplay(treeData, checkedKeys) {

            // 直接返回所有在checkedKeys中的节点ID
            return checkedKeys.filter(id => {
                // 验证ID是否存在于树数据中
                return this.findNodeInTree(treeData, id);
            });
        },
        // 在树中查找节点
        findNodeInTree(nodes, id) {
            for (const node of nodes) {
                if (node.id === id) {
                    return true;
                }
                if (node.children && node.children.length > 0) {
                    if (this.findNodeInTree(node.children, id)) {
                        return true;
                    }
                }
            }
            return false;
        },
        // 验证树状态
        validateTreeState() {
            const treeRef = this.$refs.treeRef;
            if (!treeRef) return;

            // 获取所有节点状态
            const checkedKeys = treeRef.getCheckedKeys();
            const halfCheckedKeys = treeRef.getHalfCheckedKeys();

            // 检查是否有冲突的节点状态
            const conflictKeys = checkedKeys.filter(key => halfCheckedKeys.includes(key));
            if (conflictKeys.length > 0) {
                console.warn('发现冲突的节点状态:', conflictKeys);
            }
        },
        async open(id) {
            this.visible = true;
            this.loading = true;
            this.roleId = id;
            try {
                let roleAuth = await roleGetPermissions(id);
                let authTree = await permissionTree()
                // 先设置数据
                this.data = authTree;
                this.defaultOpenIds = this.getExpandedKeys(authTree, roleAuth);

                // 使用 nextTick 确保 DOM 更新完成后再设置选中状态
                this.$nextTick(() => {
                    // 选择回显方法
                    let displayIds;
                    if (roleAuth && roleAuth.length > 0) {
                        // 使用简单回显方法，直接显示所有选中的节点
                        displayIds = this.simpleTreeDisplay(authTree, roleAuth);
                    } else {
                        // 使用复杂回显方法，处理父子节点关系
                        displayIds = this.processTreeDataForDisplay(authTree, roleAuth);
                    }

                    this.$refs.treeRef.setCheckedKeys([]);
                    // return
                    // 设置选中状态
                    this.$refs.treeRef.setCheckedKeys(displayIds);

                    // 确保树节点状态正确
                    this.$nextTick(() => {
                        this.ensureCorrectTreeState();
                        this.loading = false;
                    });
                });
            } catch (e) {
                this.loading = false;
            }
        },
        sub() {
            const ids = this.$refs.treeRef.getCheckedKeys();
            const halfCheckedKeys = this.$refs.treeRef.getHalfCheckedKeys();
            this.loading = true;

            // 合并选中的节点和半选状态的节点
            const allPermissionIds = [...ids, ...halfCheckedKeys];

            roleAssignPermissions({ permissionIds: allPermissionIds, roleId: this.roleId }).then(res => {

                this.$message({
                    type: 'success',
                    message: '分配成功',
                });
                this.visible = false
            }).finally(() => {
                this.loading = false;
            })
        }
    },
}
</script>

<style lang='scss' scoped></style>